"""
Base classes for transformation rules.

This module defines the abstract base classes and interfaces for transformation rules.
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum
from typing import Any, Optional


class TransformationPhase(str, Enum):
    """Phases in which transformations can be applied"""

    PRE_NORMALIZATION = "pre_normalization"
    NORMALIZATION = "normalization"
    POST_NORMALIZATION = "post_normalization"
    CODE_GENERATION = "code_generation"


@dataclass
class RuleMetadata:
    """Metadata for a transformation rule"""

    name: str
    version: str
    description: str
    priority: int = 100  # Lower priority executes first
    phase: TransformationPhase = TransformationPhase.NORMALIZATION
    enabled: bool = True
    tags: list[str] | None = None

    def __post_init__(self) -> None:
        if self.tags is None:
            self.tags = []


class TransformationRule(ABC):
    """
    Abstract base class for transformation rules.

    Each transformation rule defines how to transform a specific pattern
    in the IR (e.g., foreach -> for loop, property -> getter/setter).
    """

    def __init__(self, metadata: RuleMetadata) -> None:
        """
        Initialize the transformation rule.

        Args:
            metadata: Rule metadata
        """
        self.metadata = metadata

    @abstractmethod
    def can_apply(self, node: Any) -> bool:
        """
        Check if this rule can be applied to the given IR node.

        Args:
            node: IR node to check

        Returns:
            True if the rule can be applied
        """
        pass

    @abstractmethod
    def apply(self, node: Any) -> Any:
        """
        Apply the transformation to the given IR node.

        Args:
            node: IR node to transform

        Returns:
            Transformed IR node (new instance or modified original)
        """
        pass

    def get_priority(self) -> int:
        """Get the priority of this rule"""
        return self.metadata.priority

    def is_enabled(self) -> bool:
        """Check if this rule is enabled"""
        return self.metadata.enabled

    def get_phase(self) -> TransformationPhase:
        """Get the phase in which this rule should be applied"""
        return self.metadata.phase


class StatementTransformationRule(TransformationRule):
    """Base class for statement transformation rules"""

    def __init__(
        self,
        metadata: RuleMetadata,
        target_statement_kind: Optional[str] = None,
    ) -> None:
        """
        Initialize the statement transformation rule.

        Args:
            metadata: Rule metadata
            target_statement_kind: The kind of statement this rule transforms
        """
        super().__init__(metadata)
        self.target_statement_kind = target_statement_kind


class ExpressionTransformationRule(TransformationRule):
    """Base class for expression transformation rules"""

    def __init__(
        self,
        metadata: RuleMetadata,
        target_expression_kind: Optional[str] = None,
    ) -> None:
        """
        Initialize the expression transformation rule.

        Args:
            metadata: Rule metadata
            target_expression_kind: The kind of expression this rule transforms
        """
        super().__init__(metadata)
        self.target_expression_kind = target_expression_kind
